<?php
/**
 * ***********************************************************************************
 * 咨询鲤 商户PC端店铺
 * 
 * 发送短信通知
 * 开放API文档地址：https://www.shlianlu.com/console/document/api_4_2
 * 
 * @author Mr.RJH
 * @date 2025-9-18
 * @email<15213026209@163.com>
 * ***********************************************************************************
 */
namespace app\service;

use think\facade\Cache;
use think\facade\Log;

use app\model\merchant\ZxlMerchantModel;

use app\model\sms\TextMessageContentTemplateModel;
use app\model\sms\TextMessageSendTaskListModel;
use app\model\sms\TextMessageSendRecordModel;
use app\model\sms\TextMessageSignTemplateModel;
use app\model\sms\ZxlSmsVerifyCodeModel;

use lianlu\TextMessageApi;

class SendSmsService
{
    /**
     * 商户ID
     * @var string
     */
    protected $m_id;

    /**
     * 构造方法
     * SystemLogService constructor.
     */
    public function __construct($m_id = '')
    {   
        $this->m_id = $m_id;
        return $this;
    }

    /**
     * 给发送短信验证码
     * 
     * @param string $phone
     * @param string $template_id 模板ID
     * @return string
     */
    public function send_sms_verify_code($phone='',$template_id='70142136')
    { 
        $key = 'sms_code_' . $phone;
        $maxRequests = 3; // 设置最大请求次数
        $duration = 300; // 时间段，这里设置为300秒
        
        if (Cache::has($key)) {
            $count = Cache::get($key);
            if ($count >= $maxRequests) {
                throw new \Exception('请求过于频繁，请稍后再试');
            }
            Cache::set($key, $count + 1, $duration);
        } else {
            Cache::set($key, 1, $duration);
        }
        
        // 短信模板信息
        $template = TextMessageContentTemplateModel::where('template_id', $template_id)->find();
        
        $code = mt_rand(100000, 999999); // 验证码
        $variable_content[] = $code;
        // 变量替换内容
        $content = $this->getVariableStr($template['content'], $variable_content);
        $variable = $this->get_variable_content($template['content'], $template['suffix']);
        $phone_list[] = $phone;

        $textMessageApi = new TextMessageApi();
        $result = $textMessageApi->message_send($phone_list,$template['template_id'],$variable_content,intval($template['type']));

        if ($result['status'] == '00') {
            
            // 插入发送任务
            $send_id = $this->send_task($result, $template, $content, $phone_list, $variable_content);
            if ($send_id) {
                $this->update_balance($template, $variable['content'], $template['type'], 'deduct');
                // 插入发送手机号明细
                $this->send_record($send_id, $result['taskId'], $phone);
                
                // 插入发送验证码记录
                $param_2 = [
                    'mobile'   => $phone,
                    'code'   => $code,
                    'create_time'   => time(),
                    'expire_time' => time()+300,
                    'ip'     => getIp(),
                ];
                ZxlSmsVerifyCodeModel::insert($param_2);
            }
            return true;
        } else {
            throw new \Exception($result['message']);
        }
        
    }

    /**
     * 变量替换内容
     * 
     * @param array $variable_content
     * @return string
     */
    private function getVariableStr($str,$variable_content)
    {
        foreach ($variable_content as $key => $v) {
            $num = $key+1;
            $str = str_replace('{%变量'.$num.'%}',$v,$str); 
        }
        return $str;
    }

    /**
     * 记录短信发送任务
     * 
     * @param array $result 执行结果
     * @param array $template 模板内容
     * @param array $content 模板替换变量后的内容
     * @return bool
     */
    private function send_task($result, $template, $content, $phone_list, $variable_content)
    {
        $param['platform_type'] = 2; // 咨询鲤
        $param['store_id'] = $this->m_id;
        $param['type'] = $template['type'];
        $param['title'] = $template['name'];
        $param['sign_id'] = $template['sign_id'];
        $param['template_id'] = $template['template_id'];
        $param['content'] = $content;
        
        $param['create_time'] = time();
        $param['phone_list'] = json_encode($phone_list, JSON_UNESCAPED_UNICODE);
        if ($variable_content) {
            $param['variable_content'] = json_encode($variable_content, JSON_UNESCAPED_UNICODE);
        }
        $param['task_id'] = $result['taskId'];
        $result = TextMessageSendTaskListModel::insertGetId($param);

        return $result;
    }

    /**
     * 记录发送手机号明细
     * 
     * @return bool
     */
    private function send_record($send_id, $task_id, $phone)
    {
        $param_1 = [
            'send_id'   => $send_id,
            'task_id'   => $task_id,
            'phone'     => $phone,
            'create_time'   => time(),
        ];
        $result = TextMessageSendRecordModel::insert($param_1);

        return true;
    }

    /**
     * 更换变量内容
     * 
     * @param string $content 模板内容
     * @param string $suffix 模板内容后缀
     * @param string $nickname 小店名称
     * @param string $product_title 产品名称
     * @param string $code 兑换码
     * @param string $order_no 微信小店订单ID
     * @param string $product_price 产品价格
     */
    private function get_variable_content($content, $suffix, $nickname='', $product_title='', $code='', $order_no='', $product_price='')
    {
        $variables = [];
        preg_match_all('/{%变量\d+%}/', $content, $matches);
        foreach ($matches[0] as $k => $v){
            if(strpos($v,"{%变量1%}") !== false){
                $content = str_replace('{%变量1%}', $nickname, $content);
                $variables[] = $nickname;
            }
            if(strpos($v,"{%变量2%}") !== false){
                $content = str_replace('{%变量2%}', $product_title, $content);
                $variables[] = $product_title;
            }
            if(strpos($v,"{%变量3%}") !== false){
                $content = str_replace('{%变量3%}', $code, $content);
                $variables[]= $code;
            }
            if(strpos($v,"{%变量4%}") !== false){
                $content = str_replace('{%变量4%}', $order_no, $content);
                $variables[] = $order_no;
            }
            if(strpos($v,"{%变量5%}") !== false){
                $content = str_replace('{%变量5%}', $product_price, $content);
                $variables[] = $product_price;
            }
        }

        return ['variable_contnet' => $variables, 'content' => $content];
    }

    /**
     * 验证商户短信余额是否充足
     * 
     * @return bool
     */
    private function verify_balance($template, $content, $type)
    {
        // 获取签名信息
        $signName = TextMessageSignTemplateModel::where(['sign_id' => $template['sign_id']])->value('content');
        $signName = '【'.$signName.'】';
        $content_length = mb_strlen($content, 'UTF-8') + mb_strlen($template['suffix'], 'UTF-8') + mb_strlen($signName, 'UTF-8');
        // 计算短信条数 大于70给字符 按67个字符一条短信计算
        if ($content_length > 70) {
            $send_count = ceil($content_length / 67);
        } else {
            $send_count = 1;
        }

        $merchant = ZxlMerchantModel::where(['id' => $this->m_id])->find();
        if ($type == 1) {
            if ($merchant->notice_balance < $send_count) {
                return false;
            }
        } else {
            if ($merchant->marketing_balance < $send_count) {
                return false;
            }
        }
        return true;
    }

    /**
     * 更新商户短信余额
     * 
     * @param array $template 模板信息
     * @param int $content 替换变量后的内容
     * @param int $type 短信类型 
     * @param int $action 默认deduct 减少
     * 
     * @return
     */
    private function update_balance($template, $content, $type, $action = 'deduct')
    {
        // 获取签名信息
        $signName = TextMessageSignTemplateModel::where(['sign_id' => $template['sign_id']])->value('content');
        $signName = '【'.$signName.'】';
        $content_length = mb_strlen($content, 'UTF-8') + mb_strlen($template['suffix'], 'UTF-8') + mb_strlen($signName, 'UTF-8');
        // 计算短信条数 大于70给字符 按67个字符一条短信计算
        if ($content_length > 70) {
            $send_count = ceil($content_length / 67);
        } else {
            $send_count = 1;
        }

        $merchant = ZxlMerchantModel::where(['id' => $this->m_id])->find();
        if ($action == 'deduct') {
            if ($type == 1) {
                $merchant->notice_balance -= $send_count;
            } else {
                $merchant->marketing_balance -= $send_count;
            }
        } else {
            if ($type == 1) {
                $merchant->notice_balance += $send_count;
            } else {
                $merchant->marketing_balance += $send_count;
            }
        }
        $merchant->save();
        return true;
    }

}